﻿using System;
using Duhking;
using NUnit.Framework;

namespace Duhking.Tests
{
    [TestFixture]
    public class DynamicMethodExtensionsTests
    {
        public class AClassToTestWith
        {
            public bool CalledTheVoidMethod { get; set; }
            public bool DidSomething { get; private set; }
            
            public string DoSomething()
            {
                DidSomething = true;
                return "DidSomething";
            }

            public void AVoidMethod()
            {
                CalledTheVoidMethod = true;
            }
        }

        [Test]
        public void CreateMethodExecuter_Returns_A_LateBoundMethod_Delegate_Which_Calls_Method_On_Target()
        {
            var testClass = new AClassToTestWith();
            var method = typeof(AClassToTestWith).GetMethod("DoSomething");
            var executer = method.CreateMethodExecuter();
            var result = executer(testClass, new object[0]);
            Assert.That(result, Is.EqualTo("DidSomething"));
            Assert.That(testClass.DidSomething, Is.True);
        }

        [Test]
        public void CreateVoidMethodExecuter_Returns_A_VoidLateBoundMethod_Delegate_Which_Calls_Method_On_Target()
        {
            var testClass = new AClassToTestWith();
            var method = typeof(AClassToTestWith).GetMethod("AVoidMethod");
            var executer = method.CreateVoidMethodExecuter();
            executer(testClass, null);
            Assert.That(testClass.CalledTheVoidMethod, Is.True);
        }

        [Test]
        public void CreateMethodExecuterDelegate_Creates_A_VoidLateBoundMethod_Delegate_For_A_Void_Method()
        {
            var method = typeof(AClassToTestWith).GetMethod("AVoidMethod");
            var executer = method.CreateMethodExecuterDelegate();
            Assert.That(executer, Is.InstanceOf<VoidLateBoundMethod>());
        }

        [Test]
        public void CreateMethodExecuter_Create_A_LateBoundMethod_Delegate_For_A_NonVoid_Method()
        {
            var method = typeof(AClassToTestWith).GetMethod("DoSomething");
            var executer = method.CreateMethodExecuterDelegate();
            Assert.That(executer, Is.InstanceOf<LateBoundMethod>());
        }
    }
}
